home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 12 - 1996 / 12.11 Nov 96 / Challenge, Java Mini VM Code / JavaMiniVM.c
Encoding:
C/C++ Source or Header  |  1996-10-24  |  32.1 KB  |  1,804 lines  |  [TEXT/R*ch]

  1. /*  JavaMiniVM.c
  2. Copyright © 1996 Xan Gregg
  3.  
  4. The core of the interpreter is written in mostly PowerPC
  5. assember, and the parsing of the tables is done in C
  6. before interpreting begins.  I create tables of relevant
  7. data for constants, fields, and methods.  The constants
  8. data is just the address of the Java constant_pool data for
  9. that index.  For fields and methods I allocate structs
  10. with the useful data and insert a pointer to the struct
  11. into the field's or method's constant_pool entry.
  12.  
  13. So, for some up-front overhead and memory usage (16 bytes
  14. per field or method), the interpreter has less work to
  15. do when dealing with a field or method.
  16.  
  17. String objects are pointers to the constant_pool
  18. payload, just as the provided test code expects.
  19.  
  20. Objects in general are greatly simplified because of the
  21. one class limitation.  No type information is stored with
  22. any object in the heap.
  23.  
  24. Of the 10M of provided heapSpace, I use 512K for the Java
  25. heap, 512K for the Java stacks (data and return), and
  26. the rest is available for the constant, field, and method
  27. tables, which will consume less that 20 * NumConstants
  28. bytes.
  29.  
  30. The heap size and stack size can be set by the macros
  31. HEAP_K and STACK_K below.  No garbage collection is
  32. performed on the heap, so if there is lots of object
  33. creation, a larger heap may be needed.
  34.  
  35. The VM has two stacks, a data stack and a return stack.
  36. The data stack grows up from the start of the stack space,
  37. and the return stack grows down from the end of the
  38. stack space.  The data stack is used for parameters and
  39. normal Java stack operations.  The return stack is used
  40. method nesting.  Each call makes a three-entry stack frame
  41. consisting of the return address, frame pointer (start of
  42. locals), and tsBase (the method base for use by tableswitch
  43. and lookupswitch).
  44.  
  45. Having separate stacks made the parameter passing easier,
  46. but now I realize that with some extra work, I could have
  47. just put the return frame into added local variables.
  48.  
  49. The Top-Of-Stack is kept in a register.  This requires
  50. a little handshaking when the interpreter calls another
  51. function, which doesn't have access to the TOS register.
  52.  
  53. The core of the interpreter is in the assembly routine,
  54. StartVM.  Its main loop fetches and dispatches opcodes,
  55. as expected.  It includes a table with a 32-byte entry
  56. for each opcode (up through 209).  An entry consists
  57. of code to implement the opcode.  Most of them fit in
  58. 32-bytes, and any extra space is used to prime the
  59. dispatch loop.
  60.  
  61. Opcodes that take more than 7 instructions to implement
  62. can spill over to code outside of the table.  Opcodes
  63. that are particularly complex (like multianewarray)
  64. are implemented with C functions.
  65.  
  66.  
  67. Limitations:
  68. I try to safely ignore operations involving long, double,
  69. and float operands by treating these types as taking 0
  70. bytes each.  Most instructions become a NOP, and others
  71. are very simple (i2d become a POP).  However, I have
  72. realized one flaw to this system:  The untyped instructions
  73. (like DUP) may try to operate on the unsupported types.
  74. It's too late to fix now, but since the challenge will try
  75. to avoid unsupported types, it's unlikely the stack
  76. manipulation of them will be needed.
  77.  
  78. Future:
  79. With the PowerPC code done for each opcode, it would
  80. not be too tough to make a compiler that would string
  81. together the PowerPC code for each opcode in each method.
  82. */
  83.  
  84. #include <stdio.h>
  85. #include <stdlib.h>
  86. #include <string.h>
  87.  
  88. // Java types
  89. typedef signed char s1;
  90. typedef signed short s2;
  91. typedef signed long s4;
  92. typedef unsigned char u1;
  93. typedef unsigned short u2;
  94. typedef unsigned long u4;
  95.  
  96. // Set these if necessary
  97. #define HEAP_K    512
  98. #define STACK_K    512
  99.  
  100. // the CONSTANT_ id's
  101. enum {C_Utf8 = 1, C_Unicode, C_Integer, C_Float, C_Long,
  102.         C_Double, C_Class, C_String, C_Fieldref,
  103.         C_Methodref, C_InterfaceMethodref, C_NameAndType};
  104.  
  105. const u2 ACC_STATIC = 0x0008;
  106.  
  107. // The contents of my tables
  108. typedef u1 *ConstantData;
  109.  
  110. typedef struct
  111. {
  112.     u2        *fieldInfoP;
  113.     long    offset;        // in bytes
  114.     long    size;                // in bytes
  115.     u1        *type;                // ptr to sig constant
  116. } FieldData;
  117.  
  118. typedef struct
  119. {
  120.     u2        *methodInfoP;
  121.     u2        *codeAttrP;
  122.     u1        *codeP;
  123.     u4        paramCount;        // in bytes
  124. } MethodData;
  125.  
  126. // prototypes
  127. void JavaMiniVM(void *constant_pool, void *fields,
  128.     void *methods, void *classFile,
  129.     long methodToExecute, void *heapSpace,void *returnStack);
  130.  
  131. static short IndexConstants(void *constants,
  132.                                 ConstantData *indexArray);
  133. static short IndexFields(void *fields);
  134. static short IndexMethods(void *methods);
  135. static void CreateAndPush(void);
  136. static void AllocateStaticFields(void);
  137. static void ResolveFields(void);
  138. static void ResolveMethods(void);
  139. static void CountParams(MethodData *methodP);
  140. asm static long StartVM(register MethodData *methodP);
  141. static void PushConstant(long n);
  142. static u1 *TableSwitch(u1 *ip, long tsBase, long n);
  143. static u1 *LookupSwitch(u1 *ip, long tsBase, long key);
  144. static long GetNewArray(long type, long size);
  145. static long GetANewArray(long size);
  146. static void PushMultiANewArray(long classIndex,
  147.                                 long numDimensions);
  148.  
  149. // globals
  150. static long            NumMethods;
  151. static long            NumFields;
  152. static long            NumConstants;
  153. static MethodData    *Methods;
  154. static FieldData    *Fields;
  155. static ConstantData    *Constants;
  156. static long            *FP;    // frame pointer
  157. static long            *SP;    // stack pointer
  158. static long            *S0;    // stack base
  159. static long            *RP;    // return stack pointer
  160. static long            *R0;    // return stack base
  161. static long            *HP;    // heap pointer
  162. static long            *H0;    // heap base
  163. static long            TotalStatic;            // in bytes
  164. static long            TotalNonStatic;    // in bytes
  165. static long            LastField;
  166. static long            LastMethod;
  167.  
  168. /* java types
  169. typedef struct
  170. {
  171. 0    u2    attribute_name;
  172. 2    u4    attribute_length;
  173. 6    u1    info[1];
  174. } attribute_info;
  175.  
  176. typedef struct
  177. {
  178. 0    u2    access_flags;
  179. 2    u2    name_index;
  180. 4    u2    signature_index;
  181. 6    u2    attribute_count;
  182. 8    attribute_info    attributes[1];
  183. } field_info;
  184.  
  185. typedef struct
  186. {
  187. 0    u2    access_flags;
  188. 2    u2    name_index;
  189. 4    u2    signature_index;
  190. 6    u2    attribute_count;
  191. 8    attribute_info    attributes[1];
  192. } method_info;
  193.  
  194. typedef struct
  195. {
  196. 0    u1    tag;
  197. 1    u2    length;
  198. 3    u1    bytes[1];
  199. } CONSTANT_Utf8_info
  200. */
  201.  
  202. #define PUSH(a)        *SP++ = (a)
  203.  
  204. #define MethodIsStatic(n)    \
  205.     ((*Methods[n].methodInfoP & ACC_STATIC) != 0)
  206.  
  207.  
  208. //----- JavaMiniVM
  209. void JavaMiniVM(void *constant_pool, void *fields,
  210.     void *methods, void *classFile,
  211.     long methodToExecute, void *heapSpace,void *returnStack)
  212. {    
  213.     //allocate java heap
  214.     H0 = (long *) heapSpace;
  215.     HP = H0;
  216.     // allocate java stack (stack grows up in memory)
  217.     S0 = H0 + HEAP_K * 256L;    // 256 longs = 1K
  218.     SP = S0;
  219.     
  220.     // return stack based at end of stack space (grows down)
  221.     R0 = S0 + STACK_K * 256L;    // 256 longs = 1K
  222.     RP = R0;
  223.     
  224.     Constants = (ConstantData *) R0;
  225.     NumConstants = IndexConstants(constant_pool, Constants);
  226.     
  227.     Fields = (FieldData *) (Constants + NumConstants);
  228.     NumFields = IndexFields(fields);
  229.     Methods = (MethodData *) (Fields + NumFields);
  230.     NumMethods = IndexMethods(methods);
  231.     
  232.     ResolveFields();
  233.     ResolveMethods();
  234.     AllocateStaticFields();
  235.     if (!MethodIsStatic(methodToExecute))
  236.         CreateAndPush();    // so it needs an obj
  237.     *(long *) returnStack =
  238.             StartVM(&Methods[methodToExecute]);
  239.     
  240. }
  241.  
  242.  
  243. //----- IndexConstants
  244. // create on index into the constant_pool
  245. static short IndexConstants(void *constants,
  246.                                 ConstantData *indexArray)
  247. {
  248.     short    n, i;
  249.     u1        *p;
  250.     
  251.     // list is preceded by length
  252.     n = * ((u2 *) constants - 1);
  253.     p = (u1 *) constants;
  254.     LastField = 0;
  255.     LastMethod = 0;
  256.     for (i = 1; i < n; i++)
  257.     {
  258.         indexArray[i] = p;
  259.         switch (*p)
  260.         {
  261.             case C_Utf8:    p += 3 + *(u2*)(p+1); break;
  262.             case C_Unicode:    p += 3 + *(u2*)(p+1); break;
  263.             case C_Integer:    p += 5; break;
  264.             case C_Float:    p += 5; break;
  265.             case C_Long:    p += 9; i += 1; break;
  266.             case C_Double:    p += 9; i += 1; break;
  267.             case C_Class:    p += 3; break;
  268.             case C_String:    p += 3; break;
  269.             case C_Fieldref: p += 5; LastField = i; break;
  270.             case C_Methodref: p += 5; LastMethod = i; break;
  271.             case C_InterfaceMethodref: p += 5; break;
  272.             case C_NameAndType:    p += 5; break;
  273.         }
  274.     }
  275.     indexArray[0] = p;    //useful for getting to 'this_class'
  276.     return n;
  277. }
  278.  
  279.  
  280. //----- IndexFields
  281. // Gather FieldData about each field
  282. static short IndexFields(void *fields)
  283. {
  284.     short    n, i;
  285.     u1        *p;
  286.     u1        *sigP;
  287.     u2        sigIndex;
  288.     FieldData    *fieldP;
  289.     u1        c;
  290.     long    staticOffset = 0;
  291.     long    memberOffset = 0;
  292.     
  293.     // list is preceded by length
  294.     n = * ((u2 *) fields - 1);
  295.     p = (u1 *) fields;
  296.     fieldP = Fields;
  297.     for (i = 0; i < n; i++)
  298.     {
  299.         short    count;    // attribute count
  300.         
  301.         fieldP->fieldInfoP = (u2 *) p;
  302.         sigIndex = *(u2 *) (p + 4);
  303.         sigP = Constants[sigIndex];
  304.         c = *(sigP + 3);
  305.         if (c == 'L' || c == 'D' || c == 'F')
  306.             fieldP->size = 0;
  307.         else
  308.             fieldP->size = 4;
  309.         fieldP->type = sigP;
  310.         if ((*fieldP->fieldInfoP & ACC_STATIC) != 0)
  311.         {
  312.             fieldP->offset = staticOffset;
  313.             staticOffset += fieldP->size;
  314.         }
  315.         else
  316.         {
  317.             fieldP->offset = memberOffset;
  318.             memberOffset += fieldP->size;
  319.         }
  320.         // skip attributes
  321.         count = * (u2 *) (p + 6);
  322.         p += 8;
  323.         while (count > 0)
  324.         {
  325.             count -= 1;
  326.             p += 6 + *(u4 *) (p+2);
  327.         }
  328.         fieldP += 1;
  329.     }
  330.     TotalStatic = staticOffset;
  331.     TotalNonStatic = memberOffset;
  332.     return n;
  333. }
  334.  
  335.  
  336. //----- IndexMethods
  337. // Gather MethodData about each method
  338. static short IndexMethods(void *methods)
  339. {
  340.     short    n, i;
  341.     u1        *p;
  342.     MethodData    *methodP;
  343.     
  344.     // list is preceded by length
  345.     n = * ((u2 *) methods - 1);
  346.     p = (u1 *) methods;
  347.     methodP = Methods;
  348.     for (i = 0; i < n; i++)
  349.     {
  350.         short    count;    // attribute count
  351.         u2        nameIndex;
  352.         u1        *nameEntryP;
  353.         
  354.         methodP->methodInfoP = (u2 *) p;
  355.         CountParams(methodP);
  356.         count = * (u2 *) (p + 6);
  357.         p += 8;
  358.         while (count > 0)
  359.         {
  360.             nameIndex = * (u2 *) (p);
  361.             nameEntryP = Constants[nameIndex];
  362.             if (*(u2*)(nameEntryP + 1) == 4
  363.                     && *(long *) (nameEntryP + 3) == 'Code')
  364.             {    // this is the code attr
  365.                 methodP->codeAttrP = (u2 *) p;
  366.                 methodP->codeP = (u1 *) (p + 14);
  367.             }
  368.             count -= 1;
  369.             p += 6 + *(u4 *) (p+2);
  370.         }
  371.         methodP += 1;
  372.     }
  373.     return n;
  374. }
  375.  
  376.  
  377. //----- CreateAndPush
  378. // allocate 'this' and push a reference to it
  379. static void CreateAndPush(void)
  380. {
  381.     *SP = (long) HP;
  382.     SP ++;
  383.     // heap already initialized to zeros
  384.     HP = (long *) ((long) HP + TotalNonStatic);
  385. }
  386.  
  387. AllocateStaticFields
  388. static void AllocateStaticFields(void)
  389. {
  390.     // heap already initialized to zeros
  391.     HP = (long *) ((long) HP + TotalStatic);
  392. }
  393.  
  394.  
  395. //----- ResolveFields
  396. // Change the payload of CONSTANT_Fieldref items to be a
  397. // pointer into the FieldData array
  398. static void ResolveFields(void)
  399. {
  400.     short    i, j;
  401.     u1        *p;
  402.     u1        *q;
  403.     ConstantData    *constantP;
  404.     FieldData    *fieldP;
  405.     u2        nameTypeIndex;
  406.     u2        nameIndex;
  407.     
  408.     constantP = Constants+1;
  409.     for (i = 1; i <= LastField; i++)
  410.     {
  411.         p = *constantP++;
  412.         if (*p == C_Fieldref)
  413.         {
  414.             fieldP = Fields;
  415.             nameTypeIndex = *(u2*) (p + 3);
  416.             q = Constants[nameTypeIndex];
  417.             nameIndex = *(u2*) (q + 1);
  418.             for (j = 0; j < NumFields; j++)
  419.             {
  420.                 if (*(fieldP->fieldInfoP+1) == nameIndex)
  421.                 {    // found matching field ref, change it
  422.                     *(u4*) (p+1) = (u4) fieldP;
  423.                     break;
  424.                 }
  425.                 fieldP += 1;
  426.             }
  427.         }
  428.     }
  429. }
  430.  
  431.  
  432. //----- ResolveMethods
  433. // Change the payload of CONSTANT_Methodref items to be a
  434. // pointer into the MethodData array
  435. static void ResolveMethods(void)
  436. {
  437.     short    i, j;
  438.     u1        *p;
  439.     u1        *q;
  440.     ConstantData    *constantP;
  441.     MethodData    *methodP;
  442.     u2        nameTypeIndex;
  443.     u2        nameIndex;
  444.     u2        sigIndex;
  445.     
  446.     constantP = Constants+1;
  447.     for (i = 1; i <= LastMethod; i++)
  448.     {
  449.         p = *constantP++;
  450.         if (*p == C_Methodref)
  451.         {
  452.             methodP = Methods;
  453.             nameTypeIndex = *(u2*) (p + 3);
  454.             q = Constants[nameTypeIndex];
  455.             nameIndex = *(u2*) (q + 1);
  456.             sigIndex = *(u2*) (q + 3);
  457.             for (j = 0; j < NumMethods; j++)
  458.             {
  459.                 if (methodP->methodInfoP[1] == nameIndex
  460.                     && methodP->methodInfoP[2] == sigIndex)
  461.                 {    // found matching method ref, change it
  462.                     *(u4*) (p+1) = (u4) methodP;
  463.                     break;
  464.                 }
  465.                 methodP += 1;
  466.             }
  467.         }
  468.     }
  469. }
  470.  
  471.  
  472. //----- CountParams
  473. static void CountParams(MethodData *methodP)
  474. {
  475.     long    sigIndex;
  476.     long    paramCount;
  477.     u1        *sigPtr;
  478.     u2        sigLength;
  479.     u1        ch;
  480.     
  481.     sigIndex = *(methodP->methodInfoP + 2);
  482.     sigPtr = Constants[sigIndex];
  483.     sigLength = * (u2 *) (sigPtr + 1);
  484.     sigPtr += 4;    // skip tag, length and '('
  485.     if ((*methodP->methodInfoP & ACC_STATIC) == 0)
  486.         paramCount = 4;    // implicit class object parameter
  487.     else
  488.         paramCount = 0;
  489.     while (1)
  490.     {
  491.         ch = *sigPtr;
  492.         if (ch == ')')
  493.             break;
  494.         paramCount += 4;
  495.         if (ch == 'D' || ch == 'J' || ch == 'F')
  496.             paramCount -= 4;    // these are 0-byte types
  497.         else if (ch == 'L')
  498.         {    // skip class name
  499.             while (*++sigPtr != ';')
  500.                 ;
  501.         }
  502.         else if (ch == '[')
  503.         {    // we don't care what it's an array of
  504.             while (*++sigPtr == '[')
  505.                 ;
  506.             if (*sigPtr == 'L')
  507.                 while (*++sigPtr != ';')
  508.                     ;
  509.         }
  510.         sigPtr += 1;
  511.     }
  512.     ch = *++sigPtr;
  513.     methodP->paramCount = paramCount;
  514. }
  515.  
  516. #define slwi(r, n)                \
  517.     rlwinm    r, r, n, 0, 31-n;
  518.  
  519. #define times4(r)                \
  520.     rlwinm    r, r, 2, 0, 29;
  521.  
  522. // the number after 'used' indicates the number of
  523. // instructions used so far in this slot.
  524. #define used0                    \
  525.     lbz        opcode, 0(ip);        \
  526.     slwi(opcode, 5)                \
  527.     add        a, base, opcode;    \
  528.     mtctr    a;                    \
  529.     addi    ip, ip, 1;            \
  530.     bctr;                        \
  531.     nop; nop;
  532.     
  533. #define used1                    \
  534.     lbz        opcode, 0(ip);        \
  535.     slwi(opcode, 5)                \
  536.     add        a, base, opcode;    \
  537.     mtctr    a;                    \
  538.     addi    ip, ip, 1;            \
  539.     bctr;                        \
  540.     nop;
  541.     
  542. #define used2                    \
  543.     lbz        opcode, 0(ip);        \
  544.     slwi(opcode, 5)                \
  545.     add        a, base, opcode;    \
  546.     mtctr    a;                    \
  547.     addi    ip, ip, 1;            \
  548.     bctr;
  549.     
  550. #define used3                    \
  551.     lbz        opcode, 0(ip);        \
  552.     slwi(opcode, 5)                \
  553.     add        a, base, opcode;    \
  554.     mtctr    a;                    \
  555.     b        next4;
  556.     
  557. #define used4                    \
  558.     lbz        opcode, 0(ip);        \
  559.     slwi(opcode, 5)    \
  560.     add        a, base, opcode;    \
  561.     b        next3;
  562.     
  563. #define used5                    \
  564.     lbz        opcode, 0(ip);        \
  565.     slwi(opcode, 5)                \
  566.     b        next2;
  567.  
  568. #define used6                    \
  569.     lbz        opcode, 0(ip);        \
  570.     b        next1;
  571.  
  572. #define used7                    \
  573.     b        next0;
  574.  
  575. #define pushtos        \
  576.     stw        tos, 0(sp);    \
  577.     addi    sp, sp, 4;
  578.  
  579. #define poptos        \
  580.     lwzu    tos, -4(sp)
  581.  
  582. #define pushi(n)        \
  583.     stw        tos, 0(sp);    \
  584.     li        tos, n;        \
  585.     addi    sp, sp, 4;
  586.  
  587. #define pushr(r)        \
  588.     stw        tos, 0(sp);    \
  589.     mr        tos, r;        \
  590.     addi    sp, sp, 4;
  591.  
  592. // The initial return address points here.
  593. u1    ExitCode[1] = {203};
  594.  
  595.  
  596. //----- StartVM
  597. asm static long StartVM(register MethodData *methodP)
  598. {
  599.     register    long    *sp;
  600.     register    long    *rp;
  601.     register    long    *fp;
  602.     register    long    *h0;
  603.     register    long    *cp;    // Constants
  604.     register    u1        *ip;        // instruction ptr
  605.     register    u1        opcode;
  606.     register    long    tsBase;    // for tableswitch padding
  607.     register    long    a;
  608.     register    long    b;
  609.     register    long    c;
  610.     register    long    base;    // base of our opcode table
  611.     register    long    tos;
  612.     
  613.     fralloc
  614.     lwz        sp, SP
  615.     lwz        rp, RP
  616.     lwz        h0, H0
  617.     lwz        cp, Constants
  618.     lwz        a, ExitCode
  619.     stwu    a, -4(rp)            // push initial return ip
  620.     lwzu    tos, -4(sp)        // put TOS into a reg.
  621.     
  622.     // get address of opcode table
  623.     bl        nowhere
  624. nowhere:
  625.     mflr    base
  626.     // offset hard-coded since MW won't subtract labels
  627.     addi    base, base, 22*4    //table - nowhere
  628.     
  629. start_method:
  630.     stwu    fp, -4(rp)
  631.  
  632.     pushtos    // put tos (last param) in memory
  633.     mr        fp, sp
  634.     // FP points to first parameter
  635.     lwz        a, methodP->paramCount
  636.     subf    fp, a, fp
  637.     // allocate space for locals
  638.     lwz        b, methodP->codeAttrP
  639.     lhz        c, 8(b)        // max locals
  640.     times4(c)
  641.     subf    c, a, c
  642.     add        sp, sp, c
  643.     // init ip
  644.     lwz        ip, methodP->codeP
  645.     // init tsBase
  646.     andi.    tsBase, ip, 3
  647.     stwu    tsBase, -4(rp)
  648.     
  649. next0:
  650.     lbz        opcode, 0(ip)
  651. next1:
  652.     slwi(opcode, 5)
  653. next2:
  654.     add        a, base, opcode
  655. next3:
  656.     mtctr    a
  657. next4:
  658.     addi    ip, ip, 1
  659.     bctr
  660.     
  661. table:
  662.     // 0 nop
  663.     used0
  664.     // 1 aconst_null
  665.     pushi(0)
  666.     used3
  667.     // 2 iconst_m1
  668.     pushi(-1)
  669.     used3
  670.     // 3 iconst_0
  671.     pushi(0)
  672.     used3
  673.     // 4 iconst_1
  674.     pushi(1)
  675.     used3
  676.     // 5 iconst_2
  677.     pushi(2)
  678.     used3
  679.     // 6 iconst_3
  680.     pushi(3)
  681.     used3
  682.     // 7 iconst_4
  683.     pushi(4)
  684.     used3
  685.     // 8 iconst_5
  686.     pushi(5)
  687.     used3
  688.     // 9 lconst_0
  689.     used0
  690.     // 10 lconst_1
  691.     used0
  692.     // 11 fconst_0
  693.     used0
  694.     // 12 fconst_1
  695.     used0
  696.     // 13 fconst_2
  697.     used0
  698.     // 14 dconst_0
  699.     used0
  700.     // 15 dconst_1
  701.     used0
  702.     // 16 bipush
  703.     lbz        a, 0(ip)
  704.     extsb    a, a
  705.     addi    ip, ip, 1
  706.     pushr(a)
  707.     used6
  708.     // 17 sipush
  709.     lha        a, 0(ip)
  710.     addi    ip, ip, 2
  711.     pushr(a)
  712.     used5
  713.     // 18 ldc1
  714.     lbz        r3, 0(ip)
  715.     addi    ip, ip, 1
  716.     pushtos
  717.     b    ldc_more
  718.     nop;nop;nop
  719.     // 19 ldc2
  720.     lhz        r3, 0(ip)
  721.     addi    ip, ip, 2
  722.     pushtos
  723.     b    ldc_more
  724.     nop;nop;nop
  725.     // 20 ldc2w
  726.     lhz        r3, 0(ip)
  727.     addi    ip, ip, 2
  728.     pushtos
  729.     b    ldc_more
  730.     nop;nop;nop
  731.     // 21 iload
  732.     lbz        a, 0(ip)
  733.     addi    ip, ip, 1
  734.     times4(a)        // convert index to offset
  735.     pushtos
  736.     lwzx    tos, a, fp
  737.     used6
  738.     // 22 lload
  739.     used0
  740.     // 23 fload
  741.     used0
  742.     // 24 dload
  743.     used0
  744.     // 25 aload
  745.     lbz        a, 0(ip)
  746.     addi    ip, ip, 1
  747.     times4(a)        // convert index to offset
  748.     pushtos
  749.     lwzx    tos, a, fp
  750.     used6
  751.     // 26 iload_0
  752.     pushtos
  753.     lwz        tos, 0(fp)
  754.     used3
  755.     // 27 iload_1
  756.     pushtos
  757.     lwz        tos, 4(fp)
  758.     used3
  759.     // 28 iload_2
  760.     pushtos
  761.     lwz        tos, 8(fp)
  762.     used3
  763.     // 29 iload_3
  764.     pushtos
  765.     lwz        tos, 12(fp)
  766.     used3
  767.     // 30 lload_0
  768.     used0
  769.     // 31 lload_1
  770.     used0
  771.     // 32 lload_2
  772.     used0
  773.     // 33 lload_3
  774.     used0
  775.     // 34 fload_0
  776.     used0
  777.     // 35 fload_1
  778.     used0
  779.     // 36 fload_2
  780.     used0
  781.     // 37 fload_3
  782.     used0
  783.     // 38 dlload_0
  784.     used0
  785.     // 39 dload_1
  786.     used0
  787.     // 40 dload_2
  788.     used0
  789.     // 41 dload_3
  790.     used0
  791.     // 42 aload_0
  792.     pushtos
  793.     lwz        tos, 0(fp)
  794.     used3
  795.     // 43 aload_1
  796.     pushtos
  797.     lwz        tos, 4(fp)
  798.     used3
  799.     // 44 aload_2
  800.     pushtos
  801.     lwz        tos, 8(fp)
  802.     used3
  803.     // 45 aload_3
  804.     pushtos
  805.     lwz        tos, 12(fp)
  806.     used3
  807.     // 46 iaload
  808.     lwzu    b, -4(sp)    // get array address
  809.     mr        a, tos
  810.     addi    b, b, 4
  811.     times4(a)                    // convert index to offset
  812.     lwzx    tos, a, b
  813.     used5
  814.     // 47 laload
  815.     lwzu    tos, -8(sp)    // drop2
  816.     used1
  817.     // 48 faload
  818.     lwzu    tos, -8(sp)    // drop2
  819.     used1
  820.     // 49 daload
  821.     lwzu    tos, -8(sp)    // drop2
  822.     used1
  823.     // 50 aaload
  824.     lwzu    b, -4(sp)    // get array address
  825.     mr        a, tos
  826.     addi    b, b, 4
  827.     times4(a)                    // convert index to offset
  828.     lwzx    tos, a, b
  829.     used5
  830.     // 51 baload
  831.     lwzu    b, -4(sp)    // get array address
  832.     addi    b, b, 4
  833.     lbzx    tos, tos, b
  834.     extsb    tos, tos
  835.     used4
  836.     // 52 caload
  837.     lwzu    b, -4(sp)    // get array address
  838.     mr        a, tos
  839.     addi    b, b, 4
  840.     slwi(a, 1)                // convert index to offset
  841.     lhzx    tos, a, b
  842.     used5
  843.     // 53 saload
  844.     lwzu    b, -4(sp)    // get array address
  845.     mr        a, tos
  846.     addi    b, b, 4
  847.     slwi(a, 1)                // convert index to offset
  848.     lhax    tos, a, b
  849.     used5
  850.     // 54 istore
  851.     lbz        a, 0(ip)
  852.     addi    ip, ip, 1
  853.     times4(a)                    // convert index to offset
  854.     stwx    tos, a, fp
  855.     lwzu    tos, -4(sp)
  856.     used5
  857.     // 55 lstore
  858.     used0
  859.     // 56 fstore
  860.     used0
  861.     // 57 dstore
  862.     used0
  863.     // 58 astore
  864.     lbz        a, 0(ip)
  865.     addi    ip, ip, 1
  866.     times4(a)                    // convert index to offset
  867.     stwx    tos, a, fp
  868.     lwzu    tos, -4(sp)
  869.     used5
  870.     // 59 istore_0
  871.     stw        tos, 0(fp)
  872.     lwzu    tos, -4(sp)
  873.     used2
  874.     // 60 istore_1
  875.     stw        tos, 4(fp)
  876.     lwzu    tos, -4(sp)
  877.     used2
  878.     // 61 istore_2
  879.     stw        tos, 8(fp)
  880.     lwzu    tos, -4(sp)
  881.     used2
  882.     // 62 istore_3
  883.     stw        tos, 12(fp)
  884.     lwzu    tos, -4(sp)
  885.     used2
  886.     // 63 lstore_0
  887.     used0
  888.     // 64 lstore_1
  889.     used0
  890.     // 65 lstore_2
  891.     used0
  892.     // 66 lstore_3
  893.     used0
  894.     // 67 fstore_0
  895.     used0
  896.     // 68 fstore_1
  897.     used0
  898.     // 69 fstore_2
  899.     used0
  900.     // 70 fstore_3
  901.     used0
  902.     // 71 dstore_0
  903.     used0
  904.     // 72 dstore_1
  905.     used0
  906.     // 73 dstore_2
  907.     used0
  908.     // 74 dstore_3
  909.     used0
  910.     // 75 astore_0
  911.     stw        tos, 0(fp)
  912.     lwzu    tos, -4(sp)
  913.     used2
  914.     // 76 astore_1
  915.     stw        tos, 4(fp)
  916.     lwzu    tos, -4(sp)
  917.     used2
  918.     // 77 astore_2
  919.     stw        tos, 8(fp)
  920.     lwzu    tos, -4(sp)
  921.     used2
  922.     // 78 astore_3
  923.     stw        tos,12(fp)
  924.     lwzu    tos, -4(sp)
  925.     used2
  926.     // 79 iastore
  927.     lwzu    b, -4(sp)    // index
  928.     lwzu    c, -4(sp)    // array address
  929.     times4(b)                    // index to offset
  930.     addi    c, c, 4        // skip arraylength field
  931.     stwx    tos, b, c
  932.     lwzu    tos, -4(sp)
  933.     used6
  934.     // 80 lastore
  935.     lwzu    tos, -8(sp)    // drop2
  936.     used1
  937.     // 81 fastore
  938.     lwzu    tos, -8(sp)    // drop2
  939.     used1
  940.     // 82 dastore
  941.     lwzu    tos, -8(sp)    // drop2
  942.     used1
  943.     // 83 aastore
  944.     lwzu    b, -4(sp)    // index
  945.     lwzu    c, -4(sp)    // array address
  946.     times4(b)                    // index to offset
  947.     addi    c, c, 4        // skip arraylength field
  948.     stwx    tos, b, c
  949.     lwzu    tos, -4(sp)
  950.     used6
  951.     // 84 bastore
  952.     lwzu    b, -4(sp)    // index
  953.     lwzu    c, -4(sp)    // array address
  954.     addi    c, c, 4        // skip arraylength field
  955.     stbx    tos, b, c
  956.     lwzu    tos, -4(sp)
  957.     used5
  958.     // 85 castore
  959.     lwzu    b, -4(sp)    // index
  960.     lwzu    c, -4(sp)    // array address
  961.     slwi(b, 1)                // index to offset
  962.     addi    c, c, 4        // skip arraylength field
  963.     sthx    tos, b, c
  964.     lwzu    tos, -4(sp)
  965.     used6
  966.     // 86 sastore
  967.     lwzu    b, -4(sp)    // index
  968.     lwzu    c, -4(sp)    // array address
  969.     slwi(b, 1)                // index to offset
  970.     addi    c, c, 4        // skip arraylength field
  971.     sthx    tos, b, c
  972.     lwzu    tos, -4(sp)
  973.     used6
  974.     // 87 pop
  975.     lwzu    tos, -4(sp)
  976.     used1
  977.     // 88 pop2
  978.     lwzu    tos, -8(sp)
  979.     used1
  980.     // 89 dup
  981.     pushtos
  982.     used2
  983.     // 90 dup_x1
  984.     lwz        a, -4(sp)
  985.     stw        tos, -4(sp)
  986.     stw        a, 0(sp)
  987.     addi    sp, sp, 4
  988.     used4
  989.     // 91 dup_x2
  990.     lwz        a, -8(sp)
  991.     lwz        b, -4(sp)
  992.     stw        tos, -8(sp)
  993.     stw        a, -4(sp)
  994.     stw        b, 0(sp)
  995.     addi    sp, sp, 4
  996.     used6
  997.     // 92 dup2
  998.     lwz        a, -4(sp)
  999.     stw        tos, 0(sp)
  1000.     stw        a, 4(sp)
  1001.     addi    sp, sp, 8
  1002.     used4
  1003.     // 93 dup2_x1
  1004.     lwz        a, -8(sp)
  1005.     lwz        b, -4(sp)
  1006.     stw        b, -8(sp)
  1007.     stw        tos, -4(sp)
  1008.     stw        a, 0(sp)
  1009.     stw        b, 4(sp)
  1010.     addi    sp, sp, 8
  1011.     used7
  1012.     // 94 dup2_x2
  1013.     lwz        a, -12(sp)
  1014.     lwz        b, -8(sp)
  1015.     lwz        c, -4(sp)
  1016.     stw        c, -12(sp)
  1017.     stw        tos, -8(sp)
  1018.     stw        a, -4(sp)
  1019.     stw        b, 0(sp)
  1020.     b        dup2_x2_more
  1021.     // 95 swap
  1022.     lwz        a, -4(sp)
  1023.     stw        tos, -4(sp)
  1024.     mr        tos, a
  1025.     used3
  1026.     // 96 iadd
  1027.     lwzu    a, -4(sp)
  1028.     add        tos, a, tos
  1029.     used2
  1030.     // 97 ladd
  1031.     used6            // pretend we had 6 instructions already
  1032.     // stash the rest of dup2_x2 here
  1033. dup2_x2_more:
  1034.     stw        c, 4(sp)
  1035.     addi    sp, sp, 8
  1036.     used4
  1037.     // 98 fadd
  1038.     used0
  1039.     // 99 dadd
  1040.     used0
  1041.     // 100 isub
  1042.     lwzu    a, -4(sp)
  1043.     subf    tos, tos, a
  1044.     used2
  1045.     // 101 lsub
  1046.     used0
  1047.     // 102 fsub
  1048.     used0
  1049.     // 103 dsub
  1050.     used0
  1051.     // 104 imul
  1052.     lwzu    a, -4(sp)
  1053.     mullw    tos, tos, a
  1054.     used2
  1055.     // 105 lmul
  1056.     used0
  1057.     // 106 fmul
  1058.     used0
  1059.     // 107 dmul
  1060.     used0
  1061.     // 108 idiv
  1062.     lwzu    a, -4(sp)
  1063.     divw    tos, a, tos
  1064.     used2
  1065.     // 109 ldiv
  1066.     used0
  1067.     // 110 fdiv
  1068.     used0
  1069.     // 111 ddiv
  1070.     used0
  1071.     // 112 irem
  1072.     lwzu    a, -4(sp)
  1073.     divw    b, a, tos
  1074.     mullw    c, b, tos
  1075.     subf    tos, c, a
  1076.     used4
  1077.     // 113 lrem
  1078.     used0
  1079.     // 114 frem
  1080.     used0
  1081.     // 115 drem
  1082.     used0
  1083.     // 116 ineg
  1084.     neg        tos, tos
  1085.     used1
  1086.     // 117 lneg
  1087.     used0
  1088.     // 118 fneg
  1089.     used0
  1090.     // 119 dneg
  1091.     used0
  1092.     // 120 ishl
  1093.     lwzu    a, -4(sp)
  1094.     andi.    tos, tos, 31
  1095.     slw        tos, a, tos
  1096.     used3
  1097.     // 121 lshl
  1098.     lwzu    tos, -4(sp)
  1099.     used1
  1100.     // 122 ishr
  1101.     lwzu    a, -4(sp)
  1102.     andi.    tos, tos, 31
  1103.     sraw    tos, a, tos
  1104.     used3
  1105.     // 123 lshr
  1106.     lwzu    tos, -4(sp)
  1107.     used1
  1108.     // 124 iushr
  1109.     lwzu    a, -4(sp)
  1110.     andi.    tos, tos, 31
  1111.     srw        tos, a, tos
  1112.     used3
  1113.     // 125 lushr
  1114.     lwzu    tos, -4(sp)
  1115.     used1
  1116.     // 126 iand
  1117.     lwzu    a, -4(sp)
  1118.     and        tos, tos, a
  1119.     used2
  1120.     // 127 land
  1121.     used0
  1122.     // 128 ior
  1123.     lwzu    a, -4(sp)
  1124.     or        tos, tos, a
  1125.     used2
  1126.     // 129 lor
  1127.     used0
  1128.     // 130 ixor
  1129.     lwzu    a, -4(sp)
  1130.     xor        tos, tos, a
  1131.     used2
  1132.     // 131 lxor
  1133.     used0
  1134.     // 132 iinc
  1135.     lhz        b, 0(ip)
  1136.     rlwinm    a, b, 26, 16, 29
  1137.     extsb    b, b
  1138.     addi    ip, ip, 2
  1139.     lwzx    c, fp, a
  1140.     add        c, c, b
  1141.     stwx    c, fp, a
  1142.     used7
  1143.     // 133 i2l
  1144.     lwzu    tos, -4(sp)
  1145.     used1
  1146.     // 134 i2f
  1147.     lwzu    tos, -4(sp)
  1148.     used1
  1149.     // 135 i2d
  1150.     lwzu    tos, -4(sp)
  1151.     used1
  1152.     // 136 l2i
  1153.     pushi(0)
  1154.     used3
  1155.     // 137 l2f
  1156.     used0
  1157.     // 138 l2d
  1158.     used0
  1159.     // 139 f2i
  1160.     pushi(0)
  1161.     used3
  1162.     // 140 f2f
  1163.     used0
  1164.     // 141 f2d
  1165.     used0
  1166.     // 142 d2i
  1167.     pushi(0)
  1168.     used3
  1169.     // 143 d2f
  1170.     used0
  1171.     // 144 d2d
  1172.     used0
  1173.     // 145 int2byte
  1174.     extsb    tos, tos
  1175.     used1
  1176.     // 146 int2char
  1177.     andi.    tos, tos, 0xffff
  1178.     used1
  1179.     // 147 int2short
  1180.     extsh    tos, tos
  1181.     used1
  1182.     // 148 lcmp
  1183.     pushi(0)
  1184.     used3
  1185.     // 149 fcmpl
  1186.     pushi(0)
  1187.     used3
  1188.     // 150 fcmpg
  1189.     pushi(0)
  1190.     used3
  1191.     // 151 dcmpl
  1192.     pushi(0)
  1193.     used3
  1194.     // 152 dcmpg
  1195.     pushi(0)
  1196.     used3
  1197.     // 153 ifeq
  1198.     cmpi    cr0, 0, tos, 0
  1199.     lha        a, 0(ip)
  1200.     lwzu    tos, -4(sp)
  1201.     addi    ip, ip, 2
  1202.     subi    a, a, 3
  1203.     bne        next0
  1204.     add        ip, ip, a
  1205.     used7
  1206.     // 154 ifne
  1207.     cmpi    cr0, 0, tos, 0
  1208.     lha        a, 0(ip)
  1209.     lwzu    tos, -4(sp)
  1210.     addi    ip, ip, 2
  1211.     subi    a, a, 3
  1212.     beq        next0
  1213.     add        ip, ip, a
  1214.     used7
  1215.     // 155 iflt
  1216.     cmpi    cr0, 0, tos, 0
  1217.     lha        a, 0(ip)
  1218.     lwzu    tos, -4(sp)
  1219.     addi    ip, ip, 2
  1220.     subi    a, a, 3
  1221.     bge        next0
  1222.     add        ip, ip, a
  1223.     used7
  1224.     // 156 ifge
  1225.     cmpi    cr0, 0, tos, 0
  1226.     lha        a, 0(ip)
  1227.     lwzu    tos, -4(sp)
  1228.     addi    ip, ip, 2
  1229.     subi    a, a, 3
  1230.     blt        next0
  1231.     add        ip, ip, a
  1232.     used7
  1233.     // 157 ifgt
  1234.     cmpi    cr0, 0, tos, 0
  1235.     lha        a, 0(ip)
  1236.     lwzu    tos, -4(sp)
  1237.     addi    ip, ip, 2
  1238.     subi    a, a, 3
  1239.     ble        next0
  1240.     add        ip, ip, a
  1241.     used7
  1242.     // 158 ifle
  1243.     cmpi    cr0, 0, tos, 0
  1244.     lha        a, 0(ip)
  1245.     lwzu    tos, -4(sp)
  1246.     addi    ip, ip, 2
  1247.     bgt        next0
  1248. do_jump:    // shared by cmp instructions
  1249.     subi    a, a, 3
  1250.     add        ip, ip, a
  1251.     used7
  1252.     // 159 if_icmpeq
  1253.     lwz        b, -4(sp)
  1254.     cmp        cr0, 0, b, tos
  1255.     lha        a, 0(ip)
  1256.     lwzu    tos, -8(sp)
  1257.     addi    ip, ip, 2
  1258.     beq        do_jump
  1259.     used6
  1260.     // 160 if_icmpne
  1261.     lwz        b, -4(sp)
  1262.     cmp        cr0, 0, b, tos
  1263.     lha        a, 0(ip)
  1264.     lwzu    tos, -8(sp)
  1265.     addi    ip, ip, 2
  1266.     bne        do_jump
  1267.     used6
  1268.     // 161 if_icmplt
  1269.     lwz        b, -4(sp)
  1270.     cmp        cr0, 0, b, tos
  1271.     lha        a, 0(ip)
  1272.     lwzu    tos, -8(sp)
  1273.     addi    ip, ip, 2
  1274.     blt        do_jump
  1275.     used6
  1276.     // 162 if_icmpge
  1277.     lwz        b, -4(sp)
  1278.     cmp        cr0, 0, b, tos
  1279.     lha        a, 0(ip)
  1280.     lwzu    tos, -8(sp)
  1281.     addi    ip, ip, 2
  1282.     bge        do_jump
  1283.     used6
  1284.     // 163 if_icmpgt
  1285.     lwz        b, -4(sp)
  1286.     cmp        cr0, 0, b, tos
  1287.     lha        a, 0(ip)
  1288.     lwzu    tos, -8(sp)
  1289.     addi    ip, ip, 2
  1290.     bgt        do_jump
  1291.     used6
  1292.     // 164 if_icmple
  1293.     lwz        b, -4(sp)
  1294.     cmp        cr0, 0, b, tos
  1295.     lha        a, 0(ip)
  1296.     lwzu    tos, -8(sp)
  1297.     addi    ip, ip, 2
  1298.     ble        do_jump
  1299.     used6
  1300.     // 165 if_acmpeq
  1301.     lwz        b, -4(sp)
  1302.     cmp        cr0, 0, b, tos
  1303.     lha        a, 0(ip)
  1304.     lwzu    tos, -8(sp)
  1305.     addi    ip, ip, 2
  1306.     beq        do_jump
  1307.     used6
  1308.     // 166 if_acmpne
  1309.     lwz        b, -4(sp)
  1310.     cmp        cr0, 0, b, tos
  1311.     lha        a, 0(ip)
  1312.     lwzu    tos, -8(sp)
  1313.     addi    ip, ip, 2
  1314.     bne        do_jump
  1315.     used6
  1316.     // 167 goto
  1317.     lha        a, 0(ip)
  1318.     subi        ip, ip, 1
  1319.     add        ip, ip, a
  1320.     used3
  1321.     // 168 jsr
  1322.     pushtos
  1323.     lha        a, 0(ip)
  1324.     addi    tos, ip, 2    // addr of next instr
  1325.     subi    ip, ip, 1
  1326.     add        ip, ip, a
  1327.     used6
  1328.     // 169 ret
  1329.     lbz        a, 0(ip)
  1330.     times4(a)                        // convert to offset
  1331.     lwzx    ip, fp, a
  1332.     used3
  1333.     // 170 tableswitch
  1334.     mr        r3, ip
  1335.     mr        r4, tsBase
  1336.     mr        r5, tos
  1337.     bl        TableSwitch
  1338.     mr        ip, r3
  1339.     poptos
  1340.     used6
  1341.     // 171 lookupswitch
  1342.     mr        r3, ip
  1343.     mr        r4, tsBase
  1344.     mr        r5, tos
  1345.     bl        LookupSwitch
  1346.     mr        ip, r3
  1347.     poptos
  1348.     used6
  1349.     // 172 ireturn
  1350.     lwz        ip, 8(rp)
  1351.     mr        sp, fp
  1352.     lwz        fp, 4(rp)
  1353.     lwz        tsBase, 0(rp)
  1354.     addi    rp, rp, 12
  1355.     used5
  1356.     // 173 lreturn
  1357.     lwz        ip, 8(rp)
  1358.     mr        sp, fp
  1359.     lwz        fp, 4(rp)
  1360.     lwz        tsBase, 0(rp)
  1361.     lwzu    tos, -4(sp)
  1362.     addi    rp, rp, 12
  1363.     used6
  1364.     // 174 freturn
  1365.     lwz        ip, 8(rp)
  1366.     mr        sp, fp
  1367.     lwz        fp, 4(rp)
  1368.     lwz        tsBase, 0(rp)
  1369.     lwzu    tos, -4(sp)
  1370.     addi    rp, rp, 12
  1371.     used6
  1372.     // 175 dreturn
  1373.     lwz        ip, 8(rp)
  1374.     mr        sp, fp
  1375.     lwz        fp, 4(rp)
  1376.     lwz        tsBase, 0(rp)
  1377.     lwzu    tos, -4(sp)
  1378.     addi    rp, rp, 12
  1379.     used6
  1380.     // 176 areturn
  1381.     lwz        ip, 8(rp)
  1382.     mr        sp, fp
  1383.     lwz        fp, 4(rp)
  1384.     lwz        tsBase, 0(rp)
  1385.     addi    rp, rp, 12
  1386.     used5
  1387.     // 177 return
  1388.     lwz        ip, 8(rp)
  1389.     mr        sp, fp
  1390.     lwz        fp, 4(rp)
  1391.     lwz        tsBase, 0(rp)
  1392.     lwzu    tos, -4(sp)
  1393.     addi    rp, rp, 12
  1394.     used6
  1395.     // 178 getstatic
  1396.     lhz        a, 0(ip)
  1397.     addi    ip, ip, 2
  1398.     times4(a)
  1399.     lwzx    b, cp, a
  1400.     b        getstatic_more
  1401.     nop;nop;nop
  1402.     // 179 putstatic
  1403.     lhz        a, 0(ip)
  1404.     addi    ip, ip, 2
  1405.     times4(a)
  1406.     lwzx    b, cp, a
  1407.     b        putstatic_more
  1408.     nop;nop;nop
  1409.     // 180 getfield
  1410.     lhz        a, 0(ip)
  1411.     addi    ip, ip, 2
  1412.     times4(a)
  1413.     lwzx    b, cp, a
  1414.     b        getfield_more
  1415.     nop;nop;nop
  1416.     // 181 putfield
  1417.     lhz        a, 0(ip)
  1418.     addi    ip, ip, 2
  1419.     times4(a)
  1420.     lwzx    b, cp, a
  1421.     b        putfield_more
  1422.     nop;nop;nop
  1423.     // 182 invokevirtual
  1424.     lhz        a, 0(ip)
  1425.     addi    ip, ip, 2
  1426.     times4(a)                    // convert to index
  1427.     lwzx    a, cp, a
  1428.     lwz        methodP, 1(a)
  1429.     stwu    ip, -4(rp)
  1430.     b        start_method
  1431.     nop
  1432.     // 183 invokenonvirtual
  1433.     lhz        a, 0(ip)
  1434.     addi    ip, ip, 2
  1435.     times4(a)                    // convert to index
  1436.     lwzx    a, cp, a
  1437.     lwz        methodP, 1(a)
  1438.     stwu    ip, -4(rp)
  1439.     b        start_method
  1440.     nop
  1441.     // 184 invokestatic
  1442.     lhz        a, 0(ip)
  1443.     addi    ip, ip, 2
  1444.     times4(a)                    // convert to index
  1445.     lwzx    a, cp, a
  1446.     lwz        methodP, 1(a)
  1447.     stwu    ip, -4(rp)
  1448.     b        start_method
  1449.     nop
  1450.     // 185 invokeinterface
  1451.     addi    ip, ip, 2
  1452.     used1
  1453.     // 186 undefined
  1454.     used0
  1455.     // 187 new
  1456.     addi    ip, ip, 2
  1457.     used1
  1458.     // 188 newarray
  1459.     lbz        r3, 0(ip)
  1460.     addi    ip, ip, 1
  1461.     mr        r4, tos
  1462.     bl        GetNewArray
  1463.     mr        tos, r3
  1464.     used5
  1465.     // 189 anewarray
  1466.     addi    ip, ip, 2    // skip type
  1467.     mr        r3, tos
  1468.     bl        GetANewArray
  1469.     mr        tos, r3
  1470.     used4
  1471.     // 190 arraylength
  1472.     lwz        tos, 0(tos)
  1473.     used1
  1474.     // 191 athrow
  1475.     used0
  1476.     // 192 checkcast
  1477.     addi    ip, ip, 2
  1478.     used1
  1479.     // 193 instanceof
  1480.     addi    ip, ip, 2
  1481.     li        tos, 1                // assume true
  1482.     used2
  1483.     // 194 monitorenter
  1484.     poptos
  1485.     used1
  1486.     // 195 monitorexit
  1487.     poptos
  1488.     used1
  1489.     // 196 wide
  1490.     addi    ip, ip, 1
  1491.     used1
  1492.     // 197 multianewarray
  1493.     lhz        r3, 0(ip)
  1494.     lbz        r4, 2(ip)
  1495.     addi    ip, ip, 3
  1496.     pushtos
  1497.     b        multianewarray_more
  1498.     nop;nop;
  1499.     // 198 ifnull
  1500.     cmpi    cr0, 0, tos, 0
  1501.     lha        a, 0(ip)
  1502.     lwzu    tos, -4(sp)
  1503.     addi    ip, ip, 2
  1504.     subi    a, a, 3
  1505.     bne        next0
  1506.     add        ip, ip, a
  1507.     used7
  1508.     // 199 ifnonnull
  1509.     cmpi    cr0, 0, tos, 0
  1510.     lha        a, 0(ip)
  1511.     lwzu    tos, -4(sp)
  1512.     addi    ip, ip, 2
  1513.     subi    a, a, 3
  1514.     beq        next0
  1515.     add        ip, ip, a
  1516.     used7
  1517.     // 200 goto_w
  1518.     lwz        a, 0(ip)
  1519.     subi    a, a, 1
  1520.     add        ip, ip, a
  1521.     used3
  1522.     // 201 jsr_w
  1523.     pushtos
  1524.     lwz        a, 0(ip)
  1525.     addi    tos, ip, 5
  1526.     subi    a, a, 1
  1527.     add        ip, ip, a
  1528.     used6
  1529.     // 202 breakpoint
  1530.     used0
  1531.     // 203 unused - but we use it to signal final exit
  1532.     b    exitVM
  1533.     used1
  1534.     used0    // 204
  1535.     used0    // 205
  1536.     used0    // 206
  1537.     used0    // 207
  1538.     used0    // 208
  1539.     // 209 ret_w
  1540.     lhz        a, 0(ip)
  1541.     times4(a)
  1542.     lwzx    ip, fp, a
  1543.     used3
  1544.  
  1545.     // remaining opcodes unused
  1546.     
  1547. exitVM:
  1548.     mr        r3, tos    
  1549.     frfree
  1550.     blr
  1551.  
  1552. ldc_more:
  1553.     stw        sp, SP
  1554.     bl        PushConstant
  1555.     lwz        sp, SP
  1556.     poptos
  1557.     b        next0
  1558.     
  1559. multianewarray_more:
  1560.     stw        sp, SP
  1561.     bl        PushMultiANewArray
  1562.     lwz        sp, SP
  1563.     poptos
  1564.     b        next0
  1565.  
  1566. getstatic_more:
  1567.     lwz        a, 1(b)        // get fieldP
  1568.     lwz        b, 8(a)        // get size
  1569.     cmpi    cr0, 0, b, 0
  1570.     lwz        c, 4(a)        // get offset
  1571.     beq        next0
  1572.     pushtos
  1573.     lwzx    tos, h0, c
  1574.     b        next0
  1575.     
  1576. putstatic_more:
  1577.     lwz        a, 1(b)        // get fieldP
  1578.     lwz        b, 8(a)        // get size
  1579.     cmpi    cr0, 0, b, 0
  1580.     lwz        c, 4(a)        // get offset
  1581.     beq        drop1ngo
  1582.     stwx    tos, h0, c
  1583.     poptos
  1584.     b        next0
  1585.     
  1586. getfield_more:
  1587.     lwz        a, 1(b)        // get fieldP
  1588.     lwz        b, 8(a)        // get size
  1589.     cmpi    cr0, 0, b, 0
  1590.     lwz        c, 4(a)        // get offset
  1591.     beq        drop1ngo
  1592.     lwzx    tos, tos, c
  1593.     b        next0
  1594.     
  1595. putfield_more:
  1596.     lwz        a, 1(b)        // get fieldP
  1597.     lwz        b, 8(a)        // get size
  1598.     cmpi    cr0, 0, b, 0
  1599.     lwz        c, 4(a)        // get offset
  1600.     beq        drop2ngo
  1601.     lwzu    a, -4(sp)
  1602.     stwx    tos, a, c
  1603.     poptos
  1604.     b        next0
  1605.  
  1606. drop2ngo:
  1607.     poptos
  1608. drop1ngo:
  1609.     poptos
  1610.     b        next0
  1611.     
  1612. }
  1613.  
  1614.  
  1615. //----- PushConstant
  1616. static void PushConstant(long n)
  1617. {
  1618.     u1        *p;
  1619.     
  1620.     p = Constants[n];
  1621.     switch (*p++)
  1622.     {
  1623.         case C_Utf8:
  1624.         case C_Unicode:
  1625.             // since no operations act on these objects,
  1626.             // I just make the const data be the object
  1627.             // (w/o the tag) for simplicity of the test code.
  1628.             PUSH((long)p);
  1629.             break;
  1630.         case C_Integer:    PUSH(*(s4*)p); break;
  1631.         case C_Float:    break;
  1632.         case C_Long:    break;
  1633.         case C_Double:    break;
  1634.         case C_Class:    break;
  1635.         case C_String:    PushConstant(*(u2*)p); break;
  1636.         case C_Fieldref:
  1637.         case C_Methodref:
  1638.         case C_InterfaceMethodref:
  1639.         case C_NameAndType:    DebugStr("\pit can happen"); break;
  1640.     }
  1641. }
  1642.  
  1643.  
  1644. //----- TableSwitch
  1645. static u1 *TableSwitch(u1 *ip, long tsBase, long n)
  1646. {
  1647.     long    *base;
  1648.     long    defaultOffset;
  1649.     long    low;
  1650.     long    high;
  1651.     
  1652.     base = (long *) (((((long)ip-tsBase) + 3) & -4)+tsBase);
  1653.     defaultOffset = *base++;
  1654.     low = *base++;
  1655.     high = *base++;
  1656.     ip -= 1;
  1657.     
  1658.     if (n < low || n > high)
  1659.         ip += defaultOffset;
  1660.     else
  1661.         ip += base[n - low];
  1662.     return ip;
  1663. }
  1664.  
  1665.  
  1666. //----- LookupSwitch
  1667. static u1 *LookupSwitch(u1 *ip, long tsBase, long key)
  1668. {
  1669.     long    *base;
  1670.     long    defaultOffset;
  1671.     long    numPairs;
  1672.     long    match;
  1673.     
  1674.     base = (long *) (((((long)ip-tsBase) + 3) & -4)+tsBase);
  1675.     defaultOffset = *base++;
  1676.     numPairs = *base++;
  1677.     ip -= 1;
  1678.     
  1679.     while (numPairs > 0)
  1680.     {
  1681.         match = *base++;
  1682.         numPairs -= 1;
  1683.         if (key == match)
  1684.             return ip + *base;
  1685.         base += 1;
  1686.     }
  1687.     return ip + defaultOffset;
  1688. }
  1689.  
  1690.  
  1691. //----- GetNewArray
  1692. // Array object: # elements, data
  1693. // data is padded to multiple of 4
  1694. static long GetNewArray(long type, long size)
  1695. {
  1696.     long        result;
  1697.     long        elementSize;
  1698.     
  1699.     result = (long) HP;
  1700.     *HP++ = size;
  1701.     if (type == 10)                // int
  1702.         elementSize = 4;
  1703.     else if ((type & 3) == 0)    // boolean or byte
  1704.         elementSize = 1;
  1705.     else if ((type & 3) == 1)    // char or short
  1706.         elementSize = 2;
  1707.     else
  1708.         elementSize = 0;        // unsupported types
  1709.     HP += ((size * elementSize + 3) >> 2);
  1710.     return result;
  1711. }
  1712.  
  1713.  
  1714. //----- GetANewArray
  1715. static long GetANewArray(long size)
  1716. {
  1717.     long        result;
  1718.     long        elementSize;
  1719.     u4            *objectP;
  1720.     
  1721.     result = (long) HP;
  1722.     *HP++ = size;
  1723.     elementSize = 4;
  1724.     objectP = (u4*) HP;
  1725.     HP = (long *) ((u1 *) HP + size * 4);
  1726.     while (size > 0)
  1727.     {
  1728.         size -= 1;
  1729.         *objectP = (u4)HP;
  1730.         HP += elementSize;
  1731.     }
  1732.     return result;
  1733. }
  1734.  
  1735.  
  1736. //----- PushMultiANewArray
  1737. // Rather complicated function to allocate a
  1738. // multi-dimensional array as arrays of array objects.
  1739. static void PushMultiANewArray(long classIndex,
  1740.                                 long numDimensions)
  1741. {
  1742.     u1        *cp;
  1743.     long    nameIndex;
  1744.     u1        *name;
  1745.     int        type;
  1746.     long    elementSize;
  1747.     long    arrayRef;
  1748.     long    size;
  1749.     long    copies;
  1750.     long    i, j;
  1751.     long    dim;
  1752.     long    dataLongs;
  1753.     long    *subArrayRef;
  1754.     long    subArrayLongs;
  1755.     
  1756.     arrayRef = (long) HP;
  1757.     cp = Constants[classIndex];
  1758.     nameIndex = *(u2*) (cp+1);
  1759.     cp = Constants[nameIndex];
  1760.     name = cp + 3;
  1761.     type = name[numDimensions];    // skip the known '[' chars
  1762.     if (type == 'I' || type == '[')        // int or ref
  1763.         elementSize = 4;
  1764.     else if (type == 'Z' || type == 'B')    // bool or byte
  1765.         elementSize = 1;
  1766.     else if (type == 'C' || type == 'S')    // char or short
  1767.         elementSize = 2;
  1768.     else
  1769.         elementSize = 0;        // unsupported types
  1770.     copies = 1;
  1771.  
  1772.     size = *(SP-1);                // the nth dimension
  1773.     dataLongs = (size * elementSize + 3) >> 2;
  1774.     for (dim = 0; dim < numDimensions - 1; dim++)
  1775.     {
  1776.         size = *(SP-numDimensions+dim);
  1777.         if (dim == numDimensions - 2)
  1778.             subArrayLongs = dataLongs + 1;
  1779.         else
  1780.             subArrayLongs = *(SP-numDimensions+dim+1) + 1;
  1781.         subArrayRef = HP + (size + 1) * copies;
  1782.         for (i = 0; i < copies; i++)
  1783.         {
  1784.             *HP++ = size;
  1785.             for (j = 0; j < size; j++)
  1786.             {
  1787.                 *HP++ = (long) subArrayRef;
  1788.                 subArrayRef += subArrayLongs;
  1789.             }
  1790.         }
  1791.         copies *= size;
  1792.     }
  1793.     // last dim is special since it has no subarrays
  1794.     size = *(SP-1);                // the nth dimension
  1795.     for (i = 0; i < copies; i++)
  1796.     {
  1797.         *HP++ = size;
  1798.         HP += dataLongs;
  1799.     }
  1800.     SP -= numDimensions;    // remove dimensions
  1801.     PUSH(arrayRef);
  1802. }
  1803.  
  1804.